﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Modules.Commander;
using Modules.Constructor;
using Modules.Corp;
using Modules.Manager.Repositories;
using Modules.Person;
using Modules.Project;
using Modules.Project.Entitys;
using Modules.Project.Repositories;
using Modules.System.Security;
using Modules.System.User;
using PmSoft;
using PmSoft.ApplicationContext;
using PmSoft.Entity;
using PmSoft.Exceptions;
using static Modules.Person.PersonConstants;
using static Modules.Project.ProjectConstants;

namespace Modules.Manager
{
    /// <summary>
    /// 项目管理员业务逻辑类
    /// </summary>
    [UseDI(ServiceLifetime.Scoped)]
    public class ManagerService
    {
        private readonly ManagerInfoRepository managerInfoRepository;
        private readonly SecurityRepository securityRepository;
        private readonly ProjectInfoRepository projectInfoRepository;
        private readonly ProjectCorpRepository projectCorpRepository;
        private readonly ProjectService projectService;
        private readonly ProjectAttachmentService projectAttachmentService;
        private readonly IApplicationContext applicationContext;
        private readonly ConstructorService constructorService;
        private readonly CorpService corpService;
        private readonly ILogger logger;
        private readonly CommanderProjectService commanderProjectService;
        private readonly ProjectGroupService projectGroupService;
        private readonly ProjectGroupMemberService projectGroupMemberService;
        private readonly ProjectStatusChangeRecordService projectStatusChangeRecordService;

        public ManagerService(
            ManagerInfoRepository managerInfoRepository,
            SecurityRepository securityRepository,
            ProjectInfoRepository projectInfoRepository,
            ProjectCorpRepository projectCorpRepository,
            ProjectService projectService,
            ProjectAttachmentService projectAttachmentService,
            ConstructorService constructorService,
                        IApplicationContext applicationContext,
             ILogger<UserService> logger,
             CommanderProjectService commanderProjectService,
             ProjectGroupService projectGroupService,
             ProjectGroupMemberService projectGroupMemberService,
             ProjectStatusChangeRecordService projectStatusChangeRecordService,
             CorpService corpService
            )
        {
            this.managerInfoRepository = managerInfoRepository;
            this.applicationContext = applicationContext;
            this.projectInfoRepository = projectInfoRepository;
            this.securityRepository = securityRepository;
            this.projectService = projectService;
            this.projectAttachmentService = projectAttachmentService;
            this.projectCorpRepository = projectCorpRepository;
            this.logger = logger;
            this.constructorService = constructorService;
            this.commanderProjectService = commanderProjectService;
            this.projectGroupService = projectGroupService;
            this.projectGroupMemberService = projectGroupMemberService;
            this.projectStatusChangeRecordService = projectStatusChangeRecordService;
            this.corpService = corpService;
        }

        /// <summary>
        /// 创建
        /// </summary>
        /// <param name="managerInfo"></param>
        /// <param name="password"></param>
        /// <exception cref="BusinessException"></exception>
        public void CreateManage(ManagerInfo managerInfo, ProjectInfo projectInfo, string password, decimal lumpContractorCorpAmount, decimal? supervisorCorpAmount, DateTime lumpContractorCorpStartDate, DateTime lumpContractorCorpEndDate, DateTime? supervisorCorpStartDate, DateTime? supervisorCorpEndDate, bool hasSupervisor, List<string> attachments, List<string> positionAttachments, List<string> noSupervisorAttachments, List<string> earnestAttachments, PersonInfo personInfo, int? commanderId, string supervisorCorpName, string supervisorCorpCode)
        {
            bool isCreate = false;
            //若管理员存在则更新数据就行,不用拦截----hzj  2023/11/14 修改
            if (managerInfoRepository.CardNoExists(managerInfo.Cardno))
            {
                ManagerInfo oldInfo = managerInfoRepository.GetManagerInfo(managerInfo.Cardno) ?? new ManagerInfo();
                managerInfo.ManagerId = oldInfo.ManagerId;
                managerInfo.SecurityId = oldInfo.SecurityId;
            }
            try
            {
                applicationContext.Transaction.Begin();//开始事务
                //登陆安全表更新----hzj  2023/11/14 修改
                SysSecurity security = securityRepository.Get(managerInfo.SecurityId) ?? new SysSecurity();
                security.Password = SecurityPasswordHelper.EncodePassword(password, UserPasswordFormat.SM4);
                security.UserType = UserType.Manager;
                if (security.SecurityId > 0)
                {
                    securityRepository.Update(security);
                }
                else
                {
                    isCreate = true;
                    securityRepository.Insert(security);
                }
                //施工企业-项目管理员信息表更新----hzj  2023/11/14 修改
                managerInfo.SecurityId = security.SecurityId;//将安全信息表自增主键赋值给用户表
                if (managerInfo.ManagerId > 0)
                {
                    managerInfoRepository.Update(managerInfo);
                }
                else
                {
                    managerInfoRepository.Insert(managerInfo);
                }
                //新增项目信息
                if (projectInfoRepository.ExistsByPrjNum(projectInfo))
                    throw new BusinessException($"项目编号：{projectInfo.PrjNum} 已存在，不能创建");

                if (projectInfoRepository.ExistsByPrjCode(projectInfo))
                    throw new BusinessException($"项目代码：{projectInfo.GgProjectCode} 已存在，不能创建");
                projectInfo.CreateManagerId = managerInfo.ManagerId;
                projectInfo.ManagerId = managerInfo.ManagerId;
                var numSerialNum = projectService.GetProjectNumAndSerialNumber(projectInfo.AreaCode);
                projectInfo.PrjNum = numSerialNum.ProjectNum;
                projectInfo.SerialNumber = numSerialNum.SerialNumber;

                var supervisorCorp = corpService.GetCorpInfo(projectInfo.SupervisorCorpId ?? 0) ?? new()
                {
                    Name = supervisorCorpName,
                    Code = supervisorCorpCode,
                    Type = ConstructorType.企业,
                    CorpType = 企业分类.工程监理
                };
                List<ProjectAttachment> projectAttachments = new();
                foreach (var item in attachments)
                {
                    projectAttachments.Add(new ProjectAttachment()
                    {
                        Id = Guid.NewGuid().ToString().Replace("-", ""),
                        AttachmentId = item,
                        ObjectId = projectInfo.ProjectId.ToString(),
                        Tenant = 项目附件租户.Project,
                        AttachmentType = 附件类型.中标通知书,
                        CreateTime = DateTime.Now
                    });
                }
                if (!hasSupervisor)
                {
                    foreach (var item in noSupervisorAttachments)
                    {
                        projectAttachments.Add(new ProjectAttachment()
                        {
                            Id = Guid.NewGuid().ToString().Replace("-", ""),
                            AttachmentId = item,
                            ObjectId = projectInfo.ProjectId.ToString(),
                            Tenant = 项目附件租户.Project,
                            AttachmentType = 附件类型.无监理证明,
                            CreateTime = DateTime.Now
                        });
                    }
                }

                if (projectInfo.PositionCount > 1)
                {
                    foreach (var item in positionAttachments)
                    {
                        projectAttachments.Add(new ProjectAttachment()
                        {
                            Id = Guid.NewGuid().ToString().Replace("-", ""),
                            AttachmentId = item,
                            ObjectId = projectInfo.ProjectId.ToString(),
                            Tenant = 项目附件租户.Project,
                            AttachmentType = 附件类型.多地施工证明,
                            CreateTime = DateTime.Now
                        });
                    }
                }
                if (projectInfo.HasEarnestMoney.HasValue && projectInfo.HasEarnestMoney.Value)
                {
                    foreach (var item in earnestAttachments)
                    {
                        projectAttachments.Add(new ProjectAttachment()
                        {
                            Id = Guid.NewGuid().ToString().Replace("-", ""),
                            AttachmentId = item,
                            ObjectId = projectInfo.ProjectId.ToString(),
                            Tenant = 项目附件租户.Project,
                            AttachmentType = 附件类型.担保文件,
                            CreateTime = DateTime.Now
                        });
                    }
                }
                else
                {
                    projectInfo.HasEarnestMoney = false;
                    projectInfo.EarnestEndDate = null;
                    projectInfo.EarnestMoney = 0;
                    projectInfo.EarnestStartDate = null;
                    projectInfo.EarnestUnitCode = null;
                    projectInfo.EarnestUnitName = null;
                }
                if (projectInfo.ProjectId > 0)
                {
                    projectService.UpdateProjectInfoNoTransaction(projectInfo, supervisorCorp, supervisorCorpAmount ?? 0, commanderId, projectAttachments);
                }
                else
                {
                    projectService.CreateProjectInfoNoTransaction(projectInfo, supervisorCorp, supervisorCorpAmount ?? 0, commanderId, projectAttachments);
                }

                //修改Manager表的projectId
                if (isCreate)
                {
                    if (managerInfo.ProjectId == 0)
                    {
                        managerInfo.ProjectId = projectInfo.ProjectId;//修改Manager表的projectId
                    }
                }
                managerInfoRepository.Update(managerInfo);

                #region 现场管理人员

                List<int> corpIds = new()
                {
                    projectInfo.LumpContractorCorpId
                };
                ProjectGroup? projectGroup = projectGroupService.GetProjectGroupsByCordProjectId(projectInfo.ProjectId, corpIds).FirstOrDefault();
                if (projectGroup != null)
                {
                    ProjectGroupMember projectManager = new()
                    {
                        ProjectId = projectGroup.ProjectId,
                        GroupId = projectGroup.GroupId,
                        CorpId = projectGroup.CorpId,
                        PersonId = personInfo.PersonId,
                        PostCategory = 管理岗位类型.劳资管理员,
                        WorkDate = projectGroup.StartDate,
                        CreateTime = DateTime.Now,
                        StartDate = projectGroup.StartDate,
                        EndDate = projectGroup.EndDate,
                        Status = 进出场状态.进场,
                        IsManager = true
                    };
                    projectGroupMemberService.Create(projectManager);
                }

                #endregion 现场管理人员

                applicationContext.Transaction.Complete();//完成事务
            }
            catch (Exception ex)
            {
                applicationContext.Transaction.Abort();//回滚事务
                logger.LogError(ex, $"CreateManage Exception cardno:{managerInfo.Cardno}");
                throw new BusinessException($"写入项目管理员数据失败:{ex.Message}");
            }
        }

        /// <summary>
        /// author:hzj date:2023/11/14 describe:已有项目的管理员绑定更新
        /// </summary>
        /// <param name="managerInfo"></param>
        /// <param name="projectInfo"></param>
        /// <param name="password"></param>
        /// <param name="lumpContractorCorpAmount"></param>
        /// <param name="supervisorCorpAmount"></param>
        /// <param name="lumpContractorCorpStartDate"></param>
        /// <param name="lumpContractorCorpEndDate"></param>
        /// <param name="supervisorCorpStartDate"></param>
        /// <param name="supervisorCorpEndDate"></param>
        public void UpdateManageProjectInfo(ManagerInfo managerInfo, ProjectInfo projectInfo, string password, decimal lumpContractorCorpAmount, decimal? supervisorCorpAmount, DateTime lumpContractorCorpStartDate, DateTime lumpContractorCorpEndDate, DateTime? supervisorCorpStartDate, DateTime? supervisorCorpEndDate, bool hasSupervisor, List<string> attachments, List<string> positionAttachments, List<string> noSupervisorAttachments, List<string> earnestAttachments, PersonInfo personInfo, int? commanderId, string supervisorCorpName, string supervisorCorpCode)
        {
            var isCreate = false;
            if (managerInfoRepository.CardNoExists(managerInfo.Cardno))
            {
                ManagerInfo oldInfo = managerInfoRepository.GetManagerInfo(managerInfo.Cardno) ?? new ManagerInfo();
                managerInfo.ManagerId = oldInfo.ManagerId;
                managerInfo.SecurityId = oldInfo.SecurityId;
            }
            try
            {
                applicationContext.Transaction.Begin();//开始事务

                //登陆安全表更新
                SysSecurity security = securityRepository.Get(managerInfo.SecurityId) ?? new SysSecurity();
                security.Password = SecurityPasswordHelper.EncodePassword(password, UserPasswordFormat.SM4);
                security.UserType = UserType.Manager;
                if (security.SecurityId > 0)
                {
                    securityRepository.Update(security);
                }
                else
                {
                    securityRepository.Insert(security);
                }
                //施工企业-项目管理员信息表更新
                managerInfo.SecurityId = security.SecurityId;//将安全信息表自增主键赋值给用户表
                if (managerInfo.ProjectId == 0)
                {
                    managerInfo.ProjectId = projectInfo.ProjectId;//修改Manager表的projectId
                }
                if (managerInfo.ManagerId > 0)
                {
                    managerInfoRepository.Update(managerInfo);
                }
                else
                {
                    isCreate = true;
                    managerInfoRepository.Insert(managerInfo);
                }
                //项目基础信息表更新
                projectInfo.CreateManagerId = managerInfo.ManagerId;
                projectInfo.ManagerId = managerInfo.ManagerId;
                projectInfo.AuditStatus = 项目审核状态.通过;
                projectInfo.NeedCompletData = false;
                projectInfo.IsRegister = true;
                projectInfo.PrjStatus = projectInfo.ContractStartDate < DateTime.Now ? 项目状态.在建 : 项目状态.筹备;
                projectStatusChangeRecordService.Create(new ProjectStatusChangeRecord()
                {
                    OldStatus = null,
                    NewStatus = projectInfo.PrjStatus.Value,
                    ProjectId = projectInfo.ProjectId,
                    CreateTime = DateTime.Now,
                    EffectiveDate = projectInfo.ContractStartDate,
                    Remark = "管理员登记项目"
                });
                var supervisorCorp = corpService.GetCorpInfo(projectInfo.SupervisorCorpId ?? 0) ?? new CorpInfo()
                {
                    Name = supervisorCorpName,
                    Code = supervisorCorpCode,
                    Type = ConstructorType.企业,
                    CorpType = 企业分类.工程监理
                };

                if (string.IsNullOrEmpty(supervisorCorp.Code)) supervisorCorp.Code = supervisorCorpCode;
                List<ProjectAttachment> projectAttachments = new();

                foreach (var item in attachments)
                {
                    projectAttachments.Add(new ProjectAttachment()
                    {
                        Id = Guid.NewGuid().ToString().Replace("-", ""),
                        AttachmentId = item,
                        ObjectId = projectInfo.ProjectId.ToString(),
                        Tenant = 项目附件租户.Project,
                        AttachmentType = 附件类型.中标通知书,
                        CreateTime = DateTime.Now
                    });
                }
                if (!hasSupervisor)
                {
                    foreach (var item in noSupervisorAttachments)
                    {
                        projectAttachments.Add(new ProjectAttachment()
                        {
                            Id = Guid.NewGuid().ToString().Replace("-", ""),
                            AttachmentId = item,
                            ObjectId = projectInfo.ProjectId.ToString(),
                            Tenant = 项目附件租户.Project,
                            AttachmentType = 附件类型.无监理证明,
                            CreateTime = DateTime.Now
                        });
                    }
                }

                if (projectInfo.PositionCount > 1)
                {
                    foreach (var item in positionAttachments)
                    {
                        projectAttachments.Add(new ProjectAttachment()
                        {
                            Id = Guid.NewGuid().ToString().Replace("-", ""),
                            AttachmentId = item,
                            ObjectId = projectInfo.ProjectId.ToString(),
                            Tenant = 项目附件租户.Project,
                            AttachmentType = 附件类型.多地施工证明,
                            CreateTime = DateTime.Now
                        });
                    }
                }
                if (projectInfo.HasEarnestMoney.HasValue && projectInfo.HasEarnestMoney.Value)
                {
                    foreach (var item in earnestAttachments)
                    {
                        projectAttachments.Add(new ProjectAttachment()
                        {
                            Id = Guid.NewGuid().ToString().Replace("-", ""),
                            AttachmentId = item,
                            ObjectId = projectInfo.ProjectId.ToString(),
                            Tenant = 项目附件租户.Project,
                            AttachmentType = 附件类型.担保文件,
                            CreateTime = DateTime.Now
                        });
                    }
                }
                else
                {
                    projectInfo.HasEarnestMoney = false;
                    projectInfo.EarnestEndDate = null;
                    projectInfo.EarnestMoney = 0;
                    projectInfo.EarnestStartDate = null;
                    projectInfo.EarnestUnitCode = null;
                    projectInfo.EarnestUnitName = null;
                }

                if (projectInfo.ProjectId > 0)
                {
                    projectService.UpdateProjectInfoNoTransaction(projectInfo, supervisorCorp, supervisorCorpAmount ?? 0, commanderId, projectAttachments);
                }
                else
                {
                    projectService.CreateProjectInfoNoTransaction(projectInfo, supervisorCorp, supervisorCorpAmount ?? 0, commanderId, projectAttachments);
                }

                #region 现场管理人员

                List<int> corpIds = new()
                {
                    projectInfo.LumpContractorCorpId
                };
                ProjectGroup? projectGroup = projectGroupService.GetProjectGroupsByCordProjectId(projectInfo.ProjectId, corpIds).FirstOrDefault();
                if (projectGroup != null)
                {
                    ProjectGroupMember projectManager = new()
                    {
                        ProjectId = projectGroup.ProjectId,
                        GroupId = projectGroup.GroupId,
                        CorpId = projectGroup.CorpId,
                        PersonId = personInfo.PersonId,
                        PostCategory = 管理岗位类型.劳资管理员,
                        WorkDate = projectGroup.StartDate,
                        CreateTime = DateTime.Now,
                        StartDate = projectGroup.StartDate,
                        EndDate = projectGroup.EndDate,
                        Status = 进出场状态.进场,
                        IsManager = true
                    };
                    projectGroupMemberService.Create(projectManager);
                }

                #endregion 现场管理人员

                applicationContext.Transaction.Complete();//完成事务
            }
            catch (Exception ex)
            {
                applicationContext.Transaction.Abort();//回滚事务
                logger.LogError(ex, $"CreateManage Exception cardno:{managerInfo.Cardno}");
                throw new BusinessException($"写入项目管理员数据失败:{ex.Message}");
            }
        }

        /// <summary>
        /// 身份证号码是否存在
        /// </summary>
        /// <param name="cardNo"></param>
        public bool CardNoExists(string cardNo)
        {
            return managerInfoRepository.CardNoExists(cardNo);
        }

        /// <summary>
        /// 用户密码认证登录
        /// </summary>
        /// <param name="cardNo"></param>
        /// <param name="password"></param>
        public ManagerInfo? PasswordSignIn(string cardNo, string password)
        {
            var security = GetSecurity(cardNo) ?? throw new BusinessException("项目管理员身份证号码或密码错误");
            if (!SecurityPasswordHelper.CheckPassword(password, security.Password, UserPasswordFormat.SM4))
                throw new BusinessException("项目管理员身份证号码或密码错误");

            HandleLogin(security);

            var managerInfo = GetManagerInfo(cardNo);
            //ProjectInfo? projectInfo = projectInfoRepository.Get(managerInfo.ProjectId);
            //if (projectInfo == null)
            //    throw new BusinessException("当前项目管理员账号还没有关联项目信息");
            //if (projectInfo.AuditStatus != 项目审核状态.通过)
            //    throw new BusinessException("您添加的项目还没审核,暂时不能登录");
            return managerInfo;
        }

        /// <summary>
        /// 登陆处理
        /// </summary>
        /// <param name="security"></param>
        private void HandleLogin(SysSecurity security)
        {
            securityRepository.UpdateLoginInfoStatus(security, applicationContext.ClientIp, DateTime.Now);
        }

        /// <summary>
        /// 更新默认管理的项目ID
        /// </summary>
        /// <param name="manager"></param>
        /// <param name="projectId"></param>
        /// <returns></returns>
        public bool UpdateDefaultProjectId(ManagerInfo manager, int projectId)
        {
            ProjectInfo? projectInfo = projectService.GetProjectInfo(projectId) ?? throw new BusinessException("当前项目不存在，不能切换");
            if (projectInfo.AuditStatus != 项目审核状态.通过)
                throw new BusinessException("当前项目还没审核通过，不能切换");
            return managerInfoRepository.UpdateDefaultProjectId(manager, projectId);
        }

        public SysSecurity? GetSecurity(string cardNo)
        {
            var managerInfo = GetManagerInfo(cardNo);
            if (managerInfo == null)
                return null;
            return securityRepository.Get(managerInfo.SecurityId);
        }

        public ManagerInfo? GetManagerInfo(int managerId)
        {
            return managerInfoRepository.Get(managerId);
        }

        public ManagerInfo? GetManagerInfo(string cardNo)
        {
            return managerInfoRepository.GetManagerInfo(cardNo);
        }

        public IPagedList<ManagerInfo> GetManagers(ManagerQuery query, int pageIndex, int pageSize)
        {
            return managerInfoRepository.GetManagers(query, pageIndex, pageSize);
        }

        /// <summary>
        /// author:hzj date:2023/12/5 describe:修改管理员信息
        /// </summary>
        /// <param name="managerInfo"></param>
        public void Update(ManagerInfo managerInfo)
        {
            managerInfoRepository.Update(managerInfo);
        }

        /// <summary>
        /// author:hzj date:2023/12/5 describe:添加管理员信息
        /// </summary>
        /// <param name="managerInfo"></param>
        public ManagerInfo Create(ManagerInfo managerInfo)
        {
            managerInfoRepository.Insert(managerInfo);
            return managerInfo;
        }
    }
}